#!/usr/bin/python -S
"""
cmdapp_test.py: Tests for cmdapp.py
"""

__author__ = 'Andy Chu'


import cStringIO
import os
import sys
import unittest

if __name__ == '__main__':
  sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), '../..'))

import cmdapp  # module under test
import params
import records

Record = records.Record  # breaking the rules a bit


def _Convert(argv, param_definition):
  return params.ToKeywordArgs(cmdapp.ArgvToRawParams(argv, param_definition))


class CmdAppTest(unittest.TestCase):

  def setUp(self):
    pass

  def tearDown(self):
    pass

  def testParseArgv_Degenerate(self):
    self.assertEqual(cmdapp.ParseArgv([], []), {})

  def testArgvToRawParams_Degenerate(self):
    self.assertEqual(cmdapp.ArgvToRawParams([], []), {})

  def testArgvParsing(self):

    # TODO: need more tests

    PARAMS = [
        params.RequiredString('regex', pos=1),
        params.OptionalString('in-field', shortcut='i', default='item'),
        params.OptionalString('out-field', shortcut='o', default=None),
        params.OptionalBoolean('ignore-case', shortcut='g', default=False),
        params.RepeatedStrings('rest-of-args'),
        ]
    self.assertEqual(
        _Convert(['.py$'], PARAMS),
        Record(regex='.py$', rest_of_args=[]))
    self.assertEqual(
        _Convert(['-i', 'foo', '.py$'], PARAMS),
        Record(regex='.py$', in_field='foo', rest_of_args=[]))
    self.assertEqual(
        _Convert(['-i', 'foo', '-o', 'match', '.py$'], PARAMS),
        Record(
            regex='.py$', in_field='foo', out_field='match', rest_of_args=[]))
    self.assertEqual(
        _Convert(
            ['--in-field', 'foo', '-o', 'match', '.py$'], PARAMS),
        Record(
            regex='.py$', in_field='foo', out_field='match', rest_of_args=[]))
    self.assertEqual(
        _Convert(['-g', '-o', 'match', '.py$'], PARAMS),
        Record(
            regex='.py$', out_field='match', ignore_case=True,
            rest_of_args=[]))
    self.assertEqual(
        _Convert(
            ['-g', '-o', 'match', '.py$', 'dude', 'heck'], PARAMS),
        Record(
            regex='.py$', out_field='match', ignore_case=True,
            rest_of_args=['dude', 'heck']))

  def testParseArgv_Integers(self):
    PARAMS = [
        params.RequiredInteger('number', pos=1),
        ]
    self.assertEqual(
        _Convert(['3'], PARAMS),
        Record(number='3'))  # Uh, not a record anymore

  def testParseArgv_Booleans(self):
    PARAMS = [
        params.OptionalBoolean('add', shortcut='a', default=True),
        params.OptionalBoolean('ignore-case', shortcut='i', default=False),
        ]
    self.assertEqual(
        _Convert(['--add'], PARAMS),
        Record(add=True))
    self.assertEqual(
        _Convert(['--ignore-case'], PARAMS),
        Record(ignore_case=True))
    self.assertEqual(
        _Convert(['--no-add'], PARAMS),
        Record(add=False))
    self.assertEqual(
        _Convert(['--no-add', '--no-ignore-case'], PARAMS),
        Record(add=False, ignore_case=False))

    # Short syntax:
    self.assertEqual(
        _Convert(['-ai'], PARAMS),
        Record(add=True, ignore_case=True))
    self.assertEqual(
        _Convert(['-ia'], PARAMS),
        Record(add=True, ignore_case=True))

  def testParsePositionalArgs_Simple(self):
    definition = [
      params.OptionalString('argv', pos=1),
      ]
      
    record = cmdapp._ParsePositionalArgs(['foo', 'bar'], definition)
    self.assertEqual(record, Record(argv='foo'))

  def testParsePositionalArgs_Repeated(self):
    definition = [
      params.OptionalInteger('num', shortcut='n'),
      params.RepeatedStrings('argv', pos='1+'),
      ]
    record = cmdapp._ParsePositionalArgs(['foo', 'bar'], definition)
    self.assertEqual(record, Record(argv=['foo', 'bar']))

  def testParsePositionalArgs_Combined(self):
    definition = [
      params.OptionalInteger('num', shortcut='n'),
      params.RepeatedStrings('filename', pos=1),
      params.RepeatedStrings('argv', pos='2+'),
      ]
    record = cmdapp._ParsePositionalArgs(['foo', 'bar', 'baz'], definition)
    self.assertEqual(record, Record(filename='foo', argv=['bar', 'baz']))


class grep(object):
  """Test app.  Processors should be wrapped in an interface like this."""

  def __init__(self, dep):
    self._dep = dep
    self.exit_code = None

  def __call__(self, environ):
    self.environ = environ
    return self

  def __iter__(self):
    pattern = self.environ['argv'][1] 
    for line in self.environ['pcli.input']:
      if pattern in line:
        yield line
    self.exit_code = 0


class PcliTest(unittest.TestCase):

  def testGrep(self):
    return
    g = grep('blah')
    cmdapp.RunNormally(g)

  def testPcliApp(self):

    fake_stdout = cStringIO.StringIO()
    c = cmdapp.SimpleHandler(
        argv=['@grep', 'foo'], stdin=cStringIO.StringIO('foo\nbar\n'),
        stdout=fake_stdout, exit_func=lambda *_: None)

    app = grep('blah')
    c.run(app)
    self.assertEqual(fake_stdout.getvalue(), 'foo\n')


if __name__ == '__main__':
  unittest.main()
